package zpp_nape.space;
import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Circle;
import zpp_nape.shape.Edge;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Arbiter;
import zpp_nape.dynamics.Contact;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.util.Debug;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.phys.Body;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
#if swc@:keep#end class ZPP_SweepData{
    static public var zpp_pool:ZPP_SweepData;
    public var next:ZPP_SweepData;
    public var prev:ZPP_SweepData;
    public var shape:ZPP_Shape;
    public var aabb:ZPP_AABB;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){
        prev=null;
        shape=null;
        aabb=null;
    }
    public function new(){}
    #if(flash9&&flib)@:ns("flibdel")#end public inline function gt(x:ZPP_SweepData){
        return aabb.minx>x.aabb.minx;
    }
}
#if swc@:keep#end class ZPP_Island{
    static public var zpp_pool:ZPP_Island;
    public var next:ZPP_Island;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function elem()return this#if(flash9&&flib)@:ns("flibdel")#end public inline function begin()return next public var inuse:Bool;
    public var modified:Bool;
    public var pushmod:Bool;
    public var mcnt:Int;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function add(o:ZPP_Island){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("add -> "+o);
            #end
        };
        var temp={
            o.inuse=true;
            o;
        };
        temp.next=begin();
        next=temp;
        modified=true;
        mcnt++;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function addAll(x:ZPP_Island){
        {
            #if NAPE_ASSERT var res={
                x!=null;
            };
            if(!res)throw "assert("+"x!=null"+") :: "+("addAll -> "+x);
            #end
        };
        {
            var cx_ite=x.begin();
            while(cx_ite!=null){
                var i=cx_ite.elem();
                add(i);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function insert(cur:ZPP_Island,o:ZPP_Island){
        {
            #if NAPE_ASSERT var res={
                o!=null&&!has(o);
            };
            if(!res)throw "assert("+"o!=null&&!has(o)"+") :: "+("cur -> "+cur+" -> "+o);
            #end
        };
        if(cur==null){
            add(o);
            return begin();
        }
        else{
            var temp={
                o.inuse=true;
                o;
            };
            temp.next=cur.next;
            cur.next=temp;
            pushmod=modified=true;
            mcnt++;
            return temp;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop():Void{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop");
            #end
        };
        var ret=begin();
        next=ret.next;
        {
            ret.elem().inuse=false;
        };
        {};
        modified=true;
        mcnt--;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function pop_unsafe():ZPP_Island{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("pop_unsafe");
            #end
        };
        var ret=front();
        pop();
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function remove(obj:ZPP_Island):Bool{
        {
            #if NAPE_ASSERT var res={
                obj!=null&&has(obj);
            };
            if(!res)throw "assert("+"obj!=null&&has(obj)"+") :: "+("remove -> "+obj);
            #end
        };
        var pre=null;
        var cur=begin();
        var ret=false;
        while(cur!=null){
            if(cur.elem()==obj){
                erase(pre);
                ret=true;
                break;
            }
            pre=cur;
            cur=cur.next;
        }
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function erase(pre:ZPP_Island):ZPP_Island{
        {
            #if NAPE_ASSERT var res={
                !empty();
            };
            if(!res)throw "assert("+"!empty()"+") :: "+("erase -> "+pre);
            #end
        };
        if(pre==null){
            pop();
            return begin();
        }
        else{
            var old=pre.next;
            var cur=old.next;
            pre.next=cur;
            {
                old.elem().inuse=false;
            };
            {};
            modified=true;
            if(cur==null)pushmod=true;
            mcnt--;
            return cur;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function splice(pre:ZPP_Island,n:Int):ZPP_Island{
        while(n-->0&&pre.next!=null)erase(pre);
        return pre.next;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function clear(){
        if(false){
            while(!empty()){
                var old=begin();
                next=old.next;
                {
                    old.elem().inuse=false;
                };
                {};
                mcnt--;
            }
            modified=true;
            pushmod=true;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function reverse(){
        var cur=begin();
        var pre=null;
        while(cur!=null){
            var nx=cur.next;
            cur.next=pre;
            next=cur;
            pre=cur;
            cur=nx;
        }
        modified=true;
        pushmod=true;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function empty():Bool return begin()==null#if(flash9&&flib)@:ns("flibdel")#end public inline function size(){
        var cnt=0;
        var cur=begin();
        while(cur!=null){
            cnt++;
            cur=cur.next;
        }
        return cnt;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function has(obj:ZPP_Island){
        {
            #if NAPE_ASSERT var res={
                obj!=null;
            };
            if(!res)throw "assert("+"obj!=null"+") :: "+("has -> "+obj);
            #end
        };
        return({
            var ret=false;
            {
                var cx_ite=this.begin();
                while(cx_ite!=null){
                    var npite=cx_ite.elem();
                    {
                        if(npite==obj){
                            ret=true;
                            break;
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
            ret;
        });
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function front()return begin().elem()#if(flash9&&flib)@:ns("flibdel")#end public inline function back(){
        var ret=begin();
        var cur=ret;
        while(cur!=null){
            ret=cur;
            cur=cur.next;
        }
        return ret.elem();
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function iterator_at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=-1&&ind<size();
            };
            if(!res)throw "assert("+"ind>=-1&&ind<size()"+") :: "+("iterator_at -> "+ind);
            #end
        };
        var ret=begin();
        while(ind-->0&&ret!=null)ret=ret.next;
        return ret;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function at(ind:Int){
        {
            #if NAPE_ASSERT var res={
                ind>=0&&ind<size();
            };
            if(!res)throw "assert("+"ind>=0&&ind<size()"+") :: "+("at -> "+ind);
            #end
        };
        var it=iterator_at(ind);
        return if(it!=null)it.elem()else null;
    }
    public var bodies:ZNPList_ZPP_Body;
    public var sleep:Bool;
    #if(flash9&&flib)@:ns("flibdel")#end public inline function free(){}
    public function new(){
        bodies=new ZNPList_ZPP_Body();
    }
}
#if swc@:keep#end class ZPP_Space{
    public var outer:Space;
    public var gravityx:Float;
    public var gravityy:Float;
    public var wrap_gravity:Vec2;
    public function getgravity(){
        var me=this;
        wrap_gravity=new Vec2(gravityx,gravityy);
        wrap_gravity.zpp_inner.inuse=true;
        wrap_gravity.zpp_inner._invalidate=function(x:ZPP_Vec2){
            {
                me.gravityx=x.x;
                me.gravityy=x.y;
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.gravityx);
                            ret;
                            #else Math.isNaN(me.gravityx);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.gravityx)"+") :: "+("vec_set(in n: "+"me.gravity"+",in x: "+"x.x"+",in y: "+"x.y"+")");
                    #end
                };
                {
                    #if NAPE_ASSERT var res={
                        !({
                            #if flash9 var ret:Bool=untyped __global__["isNaN"](me.gravityy);
                            ret;
                            #else Math.isNaN(me.gravityy);
                            #end
                        });
                    };
                    if(!res)throw "assert("+"!assert_isNaN(me.gravityy)"+") :: "+("vec_set(in n: "+"me.gravity"+",in x: "+"x.x"+",in y: "+"x.y"+")");
                    #end
                };
            };
        }
    }
    public var bodies:ZNPList_ZPP_Body;
    public var wrap_bodies:BodyList;
    public var statics:ZNPList_ZPP_Body;
    public var wrap_statics:BodyList;
    public var dynamics:ZNPList_ZPP_Body;
    public var wrap_dynamics:BodyList;
    public var kinematics:ZNPList_ZPP_Body;
    public var wrap_kinematics:BodyList;
    public var constraints:ZNPList_ZPP_Constraint;
    public var sweep:ZPP_SweepData;
    public var stamp:Int;
    
    public var c_arbiters_false:ZNPList_ZDD;
    public var c_arbiters_true:ZNPList_ZSD;
    public var f_arbiters:ZNPList_ZPP_FluidArbiter;
    public var s_arbiters:ZNPList_ZPP_SensorArbiter;
    public var map_arb:IntHash<ZPP_Arbiter>;
    public var wrap_arbiters:ArbiterList;
    public var live:ZNPList_ZPP_Body;
    public var wrap_live:BodyList;
    public var staticsleep:ZNPList_ZPP_Body;
    public var islands:ZPP_Island;
    public var livestack:ZNPList_ZPP_Body;
    public function new(gravity:ZPP_Vec2){
        var me=this;
        if(gravity!=null){
            this.gravityx=gravity.x;
            this.gravityy=gravity.y;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](this.gravityx);
                        ret;
                        #else Math.isNaN(this.gravityx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(this.gravityx)"+") :: "+("vec_set(in n: "+"this.gravity"+",in x: "+"gravity.x"+",in y: "+"gravity.y"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](this.gravityy);
                        ret;
                        #else Math.isNaN(this.gravityy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(this.gravityy)"+") :: "+("vec_set(in n: "+"this.gravity"+",in x: "+"gravity.x"+",in y: "+"gravity.y"+")");
                #end
            };
        };
        else{
            this.gravityx=0;
            this.gravityy=0;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](this.gravityx);
                        ret;
                        #else Math.isNaN(this.gravityx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(this.gravityx)"+") :: "+("vec_set(in n: "+"this.gravity"+",in x: "+"0"+",in y: "+"0"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](this.gravityy);
                        ret;
                        #else Math.isNaN(this.gravityy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(this.gravityy)"+") :: "+("vec_set(in n: "+"this.gravity"+",in x: "+"0"+",in y: "+"0"+")");
                #end
            };
        };
        bodies=new ZNPList_ZPP_Body();
        wrap_bodies=ZPP_BodyList.get(bodies);
        wrap_bodies.zpp_inner.adder=function(x:Body){
            if(x.zpp_inner.space!=me){
                if(x.zpp_inner.space!=null)x.zpp_inner.space.outer.bodies.remove(x);
                me.addBody(x.zpp_inner,0);
                return true;
            }
            else return false;
        };
        wrap_bodies.zpp_inner.subber=function(x:Body){
            me.removeBody(x.zpp_inner,0);
        };
        statics=new ZNPList_ZPP_Body();
        wrap_statics=ZPP_BodyList.get(statics);
        wrap_statics.zpp_inner.adder=function(x:Body){
            if(x.type!=BodyType.STATIC)throw "Error: Cannot add non-"+"static"+" Body to "+"static"+"s list";
            if(x.zpp_inner.space!=me){
                if(x.zpp_inner.space!=null)x.zpp_inner.space.outer.statics.remove(x);
                me.addBody(x.zpp_inner,ZPP_Flags.id_BodyType_STATIC);
                return true;
            }
            else return false;
        }
        wrap_statics.zpp_inner.subber=function(x:Body){
            me.removeBody(x.zpp_inner,ZPP_Flags.id_BodyType_STATIC);
        }
        dynamics=new ZNPList_ZPP_Body();
        wrap_dynamics=ZPP_BodyList.get(dynamics);
        wrap_dynamics.zpp_inner.adder=function(x:Body){
            if(x.type!=BodyType.DYNAMIC)throw "Error: Cannot add non-"+"dynamic"+" Body to "+"dynamic"+"s list";
            if(x.zpp_inner.space!=me){
                if(x.zpp_inner.space!=null)x.zpp_inner.space.outer.dynamics.remove(x);
                me.addBody(x.zpp_inner,ZPP_Flags.id_BodyType_DYNAMIC);
                return true;
            }
            else return false;
        }
        wrap_dynamics.zpp_inner.subber=function(x:Body){
            me.removeBody(x.zpp_inner,ZPP_Flags.id_BodyType_DYNAMIC);
        }
        kinematics=new ZNPList_ZPP_Body();
        wrap_kinematics=ZPP_BodyList.get(kinematics);
        wrap_kinematics.zpp_inner.adder=function(x:Body){
            if(x.type!=BodyType.KINEMATIC)throw "Error: Cannot add non-"+"kinematic"+" Body to "+"kinematic"+"s list";
            if(x.zpp_inner.space!=me){
                if(x.zpp_inner.space!=null)x.zpp_inner.space.outer.kinematics.remove(x);
                me.addBody(x.zpp_inner,ZPP_Flags.id_BodyType_KINEMATIC);
                return true;
            }
            else return false;
        }
        wrap_kinematics.zpp_inner.subber=function(x:Body){
            me.removeBody(x.zpp_inner,ZPP_Flags.id_BodyType_KINEMATIC);
        }
        c_arbiters_true=new ZNPList_ZSD();
        c_arbiters_false=new ZNPList_ZDD();
        f_arbiters=new ZNPList_ZPP_FluidArbiter();
        s_arbiters=new ZNPList_ZPP_SensorArbiter();
        map_arb=new IntHash<ZPP_Arbiter>();
        islands=new ZPP_Island();
        livestack=new ZNPList_ZPP_Body();
        live=new ZNPList_ZPP_Body();
        wrap_live=ZPP_BodyList.get(live,true);
        staticsleep=new ZNPList_ZPP_Body();
        constraints=new ZNPList_ZPP_Constraint();
    }
    #if(flash9&&flib)@:ns("flibdel")#end inline public function transmitType(p:ZPP_Body,old_type:Int,new_type:Int){
        if(old_type==ZPP_Flags.id_BodyType_DYNAMIC){
            dynamics.remove(p);
            if(!p.sleeping)live.remove(p);
        }
        else if(old_type==ZPP_Flags.id_BodyType_KINEMATIC){
            kinematics.remove(p);
            if(!p.sleeping)staticsleep.remove(p);
        }
        else if(old_type==ZPP_Flags.id_BodyType_STATIC){
            statics.remove(p);
            if(!p.sleeping)staticsleep.remove(p);
        }
        if(new_type==ZPP_Flags.id_BodyType_DYNAMIC)dynamics.add(p);
        else if(new_type==ZPP_Flags.id_BodyType_KINEMATIC)kinematics.add(p);
        else if(new_type==ZPP_Flags.id_BodyType_STATIC)statics.add(p);
        if(new_type==ZPP_Flags.id_BodyType_STATIC)static_validation(p);
        p.sleeping=true;
        wake(p,true);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function added_shape(s:ZPP_Shape){
        var dat={
            if(ZPP_SweepData.zpp_pool==null)new ZPP_SweepData();
            else{
                var ret=ZPP_SweepData.zpp_pool;
                ZPP_SweepData.zpp_pool=ret.next;
                ret;
            }
        };
        s.sweep=dat;
        dat.shape=s;
        dat.aabb=s.aabb;
        dat.next=sweep;
        if(sweep!=null)sweep.prev=dat;
        sweep=dat;
        wake(s.body);
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function removed_shape(s:ZPP_Shape,?deleting=false){
        var body=s.body;
        if(!deleting){
            body.wakeall();
        }
        var pre=null;
        {
            var cx_ite=body.arbiters.begin();
            while(cx_ite!=null){
                var xarb=cx_ite.elem();
                {
                    var rem=xarb.ws1==s||xarb.ws2==s;
                    if(rem){
                        if(xarb.b1!=body&&xarb.b1.isDynamic())wake(xarb.b1);
                        if(xarb.b2!=body&&xarb.b2.isDynamic())wake(xarb.b2);
                        xarb.lazyRetire(this,body);
                        cx_ite=body.arbiters.erase(pre);
                        continue;
                    }
                    pre=cx_ite;
                };
                cx_ite=cx_ite.next;
            }
        };
        var dat=s.sweep;
        if(dat.prev==null)sweep=dat.next;
        else dat.prev.next=dat.next;
        if(dat.next!=null)dat.next.prev=dat.prev;
        {
            var o=dat;
            {
                #if NAPE_ASSERT var res={
                    o!=null;
                };
                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_SweepData"+", in obj: "+"dat"+")");
                #end
            };
            o.free();
            o.next=ZPP_SweepData.zpp_pool;
            ZPP_SweepData.zpp_pool=o;
        };
    }
    public inline function addBody(body:ZPP_Body,?flag:Int=-1){
        body.space=this;
        body.sleeping=true;
        wake(body);
        {
            var cx_ite=body.shapes.begin();
            while(cx_ite!=null){
                var shape=cx_ite.elem();
                added_shape(shape);
                cx_ite=cx_ite.next;
            }
        };
        if(body.isStatic()){
            static_validation(body);
            if(flag!=ZPP_Flags.id_BodyType_STATIC)statics.add(body);
            if(flag==-1)bodies.add(body);
        }
        else{
            if(body.isDynamic()){
                if(flag!=ZPP_Flags.id_BodyType_DYNAMIC)dynamics.add(body);
                if(flag==-1)bodies.add(body);
            }
            else{
                if(flag!=ZPP_Flags.id_BodyType_KINEMATIC)kinematics.add(body);
                if(flag==-1)bodies.add(body);
            }
        }
    }
    public inline function removeBody(body:ZPP_Body,?flag:Int=-1){
        if(body.isStatic()){
            if(flag!=ZPP_Flags.id_BodyType_STATIC)statics.remove(body);
            if(flag==-1)bodies.remove(body);
            if(!body.sleeping)staticsleep.remove(body);
        }
        else{
            if(body.isDynamic()){
                if(flag!=ZPP_Flags.id_BodyType_DYNAMIC)dynamics.remove(body);
                if(flag==-1)bodies.remove(body);
                if(!body.sleeping)live.remove(body);
            }
            else{
                if(flag!=ZPP_Flags.id_BodyType_KINEMATIC)kinematics.remove(body);
                if(flag==-1)bodies.remove(body);
                if(!body.sleeping)staticsleep.remove(body);
            }
        }
        {
            var cx_ite=body.shapes.begin();
            while(cx_ite!=null){
                var shape=cx_ite.elem();
                removed_shape(shape,true);
                cx_ite=cx_ite.next;
            }
        };
        body.removedFromSpace();
        body.space=null;
    }
    public inline function broadphase(){
        if(sweep!=null){
            var a=sweep.next;
            while(a!=null){
                var n=a.next;
                var b=a.prev;
                if(a.gt(b)){
                    a=n;
                    continue;
                }
                while(b.prev!=null&&b.prev.gt(a))b=b.prev;
                var prev=a.prev;
                prev.next=a.next;
                if(a.next!=null)a.next.prev=prev;
                if(b.prev==null){
                    a.prev=null;
                    sweep=a;
                    a.next=b;
                    b.prev=a;
                }
                else{
                    a.prev=b.prev;
                    b.prev=a;
                    a.prev.next=a;
                    a.next=b;
                }
                a=n;
            }
            var d1=sweep;
            while(d1!=null){
                var d2=d1.next;
                var bottom=d1.aabb.maxx;
                while(d2!=null){
                    if(d2.aabb.minx>bottom)break;
                    var s1=d1.shape;
                    var s2=d2.shape;
                    if(s1.body.isStatic()&&s2.body.isStatic()){
                        d2=d2.next;
                        continue;
                    }
                    if(s1.body.sleeping&&s2.body.sleeping){
                        d2=d2.next;
                        continue;
                    }
                    if(s1.aabb.intersectY(s2.aabb)){
                        if(s1.body.isStatic())narrowPhase_true(s1,s2);
                        else if(s2.body.isStatic())narrowPhase_true(s2,s1);
                        else narrowPhase_false(s1,s2);
                    }
                    d2=d2.next;
                }
                d1=d1.next;
            }
        }
    }
    public function step(deltaTime:Float,?elasticIterations:Int=6,?stackingIterations:Int=6){
        var idt=1/deltaTime;
        stamp++;
        updatePos(deltaTime);
        validation(idt);
        broadphase();
        doForests(deltaTime);
        prestep(deltaTime);
        iterate(elasticIterations,true);
        updateVel(deltaTime);
        warmStart();
        iterate(stackingIterations,false);
        updatePosBias();
        while(!staticsleep.empty()){
            var b=staticsleep.pop_unsafe();
            {
                #if NAPE_ASSERT var res={
                    !b.isDynamic();
                };
                if(!res)throw "assert("+"!b.isDynamic()"+") :: "+("step :: swef static/kinematics");
                #end
            };
            b.sleeping=true;
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function wake_connected(o:ZPP_Body){
        {
            var cx_ite=o.arbiters.begin();
            while(cx_ite!=null){
                var arb=cx_ite.elem();
                {
                    if(arb.type==ZPP_Arbiter.SENSOR){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    if(!arb.cleared&&(arb.sleeping||arb.up_stamp==stamp)){
                        if(arb.b1!=o&&arb.b1.isDynamic())wake(arb.b1);
                        if(arb.b2!=o&&arb.b2.isDynamic())wake(arb.b2);
                    }
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function wake(o:ZPP_Body,force=false){
        o.waket=stamp+1;
        var was_sleep=o.sleeping;
        if(o.sleeping||force){
            o.sleeping=false;
            if(o.isKinematic()||o.isStatic())staticsleep.add(o);
            else if(was_sleep)live.add(o);
            return true;
        }
        else return false;
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function doForests(dt:Float){
        {
            var cx_ite=kinematics.begin();
            while(cx_ite!=null){
                var kin=cx_ite.elem();
                {
                    if(kin.sleeping){
                        cx_ite=cx_ite.next;
                        continue;
                    };
                    {
                        var cx_ite=kin.arbiters.begin();
                        while(cx_ite!=null){
                            var arb=cx_ite.elem();
                            {
                                if(arb.sleeping){
                                    arb.sleeping=false;
                                    arb.up_stamp+=stamp-arb.sleep_stamp;
                                    if(arb.type==ZPP_Arbiter.COL){
                                        var carb=arb.colarb;
                                        if(carb.kind==ZPP_ColArbiter.DD)c_arbiters_false.add(carb.aDD);
                                        else c_arbiters_true.add(carb.aSD);
                                    }
                                    else if(arb.type==ZPP_Arbiter.FLUID){
                                        f_arbiters.add(arb.fluidarb);
                                    }
                                    else{
                                        s_arbiters.add(arb.sensorarb);
                                    }
                                }
                            };
                            cx_ite=cx_ite.next;
                        }
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
        {
            var cx_ite=live.begin();
            while(cx_ite!=null){
                var obj=cx_ite.elem();
                {
                    {
                        var cx_ite=obj.arbiters.begin();
                        while(cx_ite!=null){
                            var arb=cx_ite.elem();
                            {
                                if(arb.sleeping){
                                    arb.sleeping=false;
                                    arb.up_stamp+=stamp-arb.sleep_stamp;
                                    if(arb.type==ZPP_Arbiter.COL){
                                        var carb=arb.colarb;
                                        if(carb.kind==ZPP_ColArbiter.DD)c_arbiters_false.add(carb.aDD);
                                        else c_arbiters_true.add(carb.aSD);
                                    }
                                    else if(arb.type==ZPP_Arbiter.FLUID){
                                        f_arbiters.add(arb.fluidarb);
                                    }
                                    else s_arbiters.add(arb.sensorarb);
                                }
                                if(arb.up_stamp==stamp&&arb.fstamp<stamp){
                                    arb.fstamp=stamp;
                                    if(arb.type==ZPP_Arbiter.COL){
                                        var carb=arb.colarb;
                                        if(carb.kind==ZPP_ColArbiter.DD){
                                            if(arb.b1.isKinematic()||arb.b2.isKinematic()){}
                                            else{
                                                if(!arb.b1.sleeping&&!arb.b2.sleeping){
                                                    var xr={
                                                        if(arb.b1==arb.b1.parent)arb.b1;
                                                        else{
                                                            var obj:ZPP_Body=arb.b1;
                                                            var stack:ZPP_Body=null;
                                                            while(obj!=obj.parent){
                                                                var nxt=obj.parent;
                                                                obj.parent=stack;
                                                                stack=obj;
                                                                obj=nxt;
                                                            }
                                                            while(stack!=null){
                                                                var nxt=stack.parent;
                                                                stack.parent=obj;
                                                                stack=nxt;
                                                            }
                                                            obj;
                                                        }
                                                    };
                                                    var yr={
                                                        if(arb.b2==arb.b2.parent)arb.b2;
                                                        else{
                                                            var obj:ZPP_Body=arb.b2;
                                                            var stack:ZPP_Body=null;
                                                            while(obj!=obj.parent){
                                                                var nxt=obj.parent;
                                                                obj.parent=stack;
                                                                stack=obj;
                                                                obj=nxt;
                                                            }
                                                            while(stack!=null){
                                                                var nxt=stack.parent;
                                                                stack.parent=obj;
                                                                stack=nxt;
                                                            }
                                                            obj;
                                                        }
                                                    };
                                                    if(xr!=yr){
                                                        if(xr.rank<yr.rank)xr.parent=yr;
                                                        else if(xr.rank>yr.rank)yr.parent=xr;
                                                        else{
                                                            yr.parent=xr;
                                                            xr.rank++;
                                                        }
                                                    }
                                                };
                                                else{
                                                    if(wake(arb.b1))livestack.add(arb.b1);
                                                    if(wake(arb.b2))livestack.add(arb.b2);
                                                }
                                            }
                                        }
                                    }
                                    else if(arb.type==ZPP_Arbiter.FLUID){
                                        if(!arb.b1.isDynamic()||!arb.b2.isDynamic()){}
                                        else{
                                            if(!arb.b1.sleeping&&!arb.b2.sleeping){
                                                var xr={
                                                    if(arb.b1==arb.b1.parent)arb.b1;
                                                    else{
                                                        var obj:ZPP_Body=arb.b1;
                                                        var stack:ZPP_Body=null;
                                                        while(obj!=obj.parent){
                                                            var nxt=obj.parent;
                                                            obj.parent=stack;
                                                            stack=obj;
                                                            obj=nxt;
                                                        }
                                                        while(stack!=null){
                                                            var nxt=stack.parent;
                                                            stack.parent=obj;
                                                            stack=nxt;
                                                        }
                                                        obj;
                                                    }
                                                };
                                                var yr={
                                                    if(arb.b2==arb.b2.parent)arb.b2;
                                                    else{
                                                        var obj:ZPP_Body=arb.b2;
                                                        var stack:ZPP_Body=null;
                                                        while(obj!=obj.parent){
                                                            var nxt=obj.parent;
                                                            obj.parent=stack;
                                                            stack=obj;
                                                            obj=nxt;
                                                        }
                                                        while(stack!=null){
                                                            var nxt=stack.parent;
                                                            stack.parent=obj;
                                                            stack=nxt;
                                                        }
                                                        obj;
                                                    }
                                                };
                                                if(xr!=yr){
                                                    if(xr.rank<yr.rank)xr.parent=yr;
                                                    else if(xr.rank>yr.rank)yr.parent=xr;
                                                    else{
                                                        yr.parent=xr;
                                                        xr.rank++;
                                                    }
                                                }
                                            };
                                            else{
                                                if(wake(arb.b1))livestack.add(arb.b1);
                                                if(wake(arb.b2))livestack.add(arb.b2);
                                            }
                                        }
                                    }
                                }
                            };
                            cx_ite=cx_ite.next;
                        }
                    };
                };
                cx_ite=cx_ite.next;
            }
        };
        while(!livestack.empty()){
            var obj=livestack.pop_unsafe();
            {
                {
                    var cx_ite=obj.arbiters.begin();
                    while(cx_ite!=null){
                        var arb=cx_ite.elem();
                        {
                            if(arb.sleeping){
                                arb.sleeping=false;
                                arb.up_stamp+=stamp-arb.sleep_stamp;
                                if(arb.type==ZPP_Arbiter.COL){
                                    var carb=arb.colarb;
                                    if(carb.kind==ZPP_ColArbiter.DD)c_arbiters_false.add(carb.aDD);
                                    else c_arbiters_true.add(carb.aSD);
                                }
                                else if(arb.type==ZPP_Arbiter.FLUID){
                                    f_arbiters.add(arb.fluidarb);
                                }
                                else s_arbiters.add(arb.sensorarb);
                            }
                            if(arb.up_stamp==stamp&&arb.fstamp<stamp){
                                arb.fstamp=stamp;
                                if(arb.type==ZPP_Arbiter.COL){
                                    var carb=arb.colarb;
                                    if(carb.kind==ZPP_ColArbiter.DD){
                                        if(arb.b1.isKinematic()||arb.b2.isKinematic()){}
                                        else{
                                            if(!arb.b1.sleeping&&!arb.b2.sleeping){
                                                var xr={
                                                    if(arb.b1==arb.b1.parent)arb.b1;
                                                    else{
                                                        var obj:ZPP_Body=arb.b1;
                                                        var stack:ZPP_Body=null;
                                                        while(obj!=obj.parent){
                                                            var nxt=obj.parent;
                                                            obj.parent=stack;
                                                            stack=obj;
                                                            obj=nxt;
                                                        }
                                                        while(stack!=null){
                                                            var nxt=stack.parent;
                                                            stack.parent=obj;
                                                            stack=nxt;
                                                        }
                                                        obj;
                                                    }
                                                };
                                                var yr={
                                                    if(arb.b2==arb.b2.parent)arb.b2;
                                                    else{
                                                        var obj:ZPP_Body=arb.b2;
                                                        var stack:ZPP_Body=null;
                                                        while(obj!=obj.parent){
                                                            var nxt=obj.parent;
                                                            obj.parent=stack;
                                                            stack=obj;
                                                            obj=nxt;
                                                        }
                                                        while(stack!=null){
                                                            var nxt=stack.parent;
                                                            stack.parent=obj;
                                                            stack=nxt;
                                                        }
                                                        obj;
                                                    }
                                                };
                                                if(xr!=yr){
                                                    if(xr.rank<yr.rank)xr.parent=yr;
                                                    else if(xr.rank>yr.rank)yr.parent=xr;
                                                    else{
                                                        yr.parent=xr;
                                                        xr.rank++;
                                                    }
                                                }
                                            };
                                            else{
                                                if(wake(arb.b1))livestack.add(arb.b1);
                                                if(wake(arb.b2))livestack.add(arb.b2);
                                            }
                                        }
                                    }
                                }
                                else if(arb.type==ZPP_Arbiter.FLUID){
                                    if(!arb.b1.isDynamic()||!arb.b2.isDynamic()){}
                                    else{
                                        if(!arb.b1.sleeping&&!arb.b2.sleeping){
                                            var xr={
                                                if(arb.b1==arb.b1.parent)arb.b1;
                                                else{
                                                    var obj:ZPP_Body=arb.b1;
                                                    var stack:ZPP_Body=null;
                                                    while(obj!=obj.parent){
                                                        var nxt=obj.parent;
                                                        obj.parent=stack;
                                                        stack=obj;
                                                        obj=nxt;
                                                    }
                                                    while(stack!=null){
                                                        var nxt=stack.parent;
                                                        stack.parent=obj;
                                                        stack=nxt;
                                                    }
                                                    obj;
                                                }
                                            };
                                            var yr={
                                                if(arb.b2==arb.b2.parent)arb.b2;
                                                else{
                                                    var obj:ZPP_Body=arb.b2;
                                                    var stack:ZPP_Body=null;
                                                    while(obj!=obj.parent){
                                                        var nxt=obj.parent;
                                                        obj.parent=stack;
                                                        stack=obj;
                                                        obj=nxt;
                                                    }
                                                    while(stack!=null){
                                                        var nxt=stack.parent;
                                                        stack.parent=obj;
                                                        stack=nxt;
                                                    }
                                                    obj;
                                                }
                                            };
                                            if(xr!=yr){
                                                if(xr.rank<yr.rank)xr.parent=yr;
                                                else if(xr.rank>yr.rank)yr.parent=xr;
                                                else{
                                                    yr.parent=xr;
                                                    xr.rank++;
                                                }
                                            }
                                        };
                                        else{
                                            if(wake(arb.b1))livestack.add(arb.b1);
                                            if(wake(arb.b2))livestack.add(arb.b2);
                                        }
                                    }
                                }
                            }
                        };
                        cx_ite=cx_ite.next;
                    }
                };
            };
        }
        while(!live.empty()){
            var o=live.pop_unsafe();
            var root={
                if(o==o.parent)o;
                else{
                    var obj:ZPP_Body=o;
                    var stack:ZPP_Body=null;
                    while(obj!=obj.parent){
                        var nxt=obj.parent;
                        obj.parent=stack;
                        stack=obj;
                        obj=nxt;
                    }
                    while(stack!=null){
                        var nxt=stack.parent;
                        stack.parent=obj;
                        stack=nxt;
                    }
                    obj;
                }
            };
            if(root.island==null){
                root.island={
                    if(ZPP_Island.zpp_pool==null)new ZPP_Island();
                    else{
                        var ret=ZPP_Island.zpp_pool;
                        ZPP_Island.zpp_pool=ret.next;
                        ret;
                    }
                };
                islands.add(root.island);
                root.island.sleep=false;
            }
            o.island=root.island;
            o.island.bodies.add(o);
            var rest=o.atRest();
            o.island.sleep=o.island.sleep&&rest;
            o.parent=o;
            o.rank=0;
        }
        while(!islands.empty()){
            var i=islands.pop_unsafe();
            while(!i.bodies.empty()){
                var o=i.bodies.pop_unsafe();
                if(i.sleep){
                    {
                        o.velx=0;
                        o.vely=0;
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](o.velx);
                                    ret;
                                    #else Math.isNaN(o.velx);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(o.velx)"+") :: "+("vec_set(in n: "+"o.vel"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](o.vely);
                                    ret;
                                    #else Math.isNaN(o.vely);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(o.vely)"+") :: "+("vec_set(in n: "+"o.vel"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                    };
                    o.angvel=0;
                    {
                        o.forcex=0;
                        o.forcey=0;
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](o.forcex);
                                    ret;
                                    #else Math.isNaN(o.forcex);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(o.forcex)"+") :: "+("vec_set(in n: "+"o.force"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](o.forcey);
                                    ret;
                                    #else Math.isNaN(o.forcey);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(o.forcey)"+") :: "+("vec_set(in n: "+"o.force"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                    };
                    o.torque=0;
                }
                else live.add(o);
                o.sleeping=i.sleep;
                o.island=null;
            }
            {
                var o=i;
                {
                    #if NAPE_ASSERT var res={
                        o!=null;
                    };
                    if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_Island"+", in obj: "+"i"+")");
                    #end
                };
                o.free();
                o.next=ZPP_Island.zpp_pool;
                ZPP_Island.zpp_pool=o;
            };
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function static_validation(body:ZPP_Body){
        body.validate_aabb();
        body.validate_mass();
        body.validate_inertia();
        {
            var cx_ite=body.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                {
                    if(s.isPolygon()){
                        s.polygon.validate_gaxi();
                        var res=s.polygon.valid();
                        if(res!=ValidationResult.VALID){
                            throw "Error: Cannot simulate with an invalid Polygon : "+s.polygon.outer.toString()+" is invalid : "+res.toString();
                        }
                    }
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function validation(idt:Float){
        {
            {
                var cx_ite=live.begin();
                while(cx_ite!=null){
                    var cur=cx_ite.elem();
                    {
                        if(cur.shapes.empty())throw "Error: Cannot simulate an empty Body";
                        cur.validate_mass();
                        cur.validate_inertia();
                        cur.validate_aabb();
                        cur.validate_gravMass();
                        cur.validate_worldCOM();
                        cur.validate_axis();
                        {
                            var cx_ite=cur.shapes.begin();
                            while(cx_ite!=null){
                                var s=cx_ite.elem();
                                {
                                    if(s.isPolygon()){
                                        var res=s.polygon.valid();
                                        if(res!=ValidationResult.VALID){
                                            throw "Error: Cannot simulate with an invalid Polygon : "+s.polygon.outer.toString()+" is invalid : "+res.toString();
                                        }
                                        s.polygon.validate_gaxi();
                                    }
                                };
                                cx_ite=cx_ite.next;
                            }
                        };
                        if(false){
                            {
                                cur.velx=cur.kinvelx;
                                cur.vely=cur.kinvely;
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.velx);
                                            ret;
                                            #else Math.isNaN(cur.velx);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(cur.velx)"+") :: "+("vec_set(in n: "+"cur.vel"+",in x: "+"cur.kinvelx"+",in y: "+"cur.kinvely"+")");
                                    #end
                                };
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.vely);
                                            ret;
                                            #else Math.isNaN(cur.vely);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(cur.vely)"+") :: "+("vec_set(in n: "+"cur.vel"+",in x: "+"cur.kinvelx"+",in y: "+"cur.kinvely"+")");
                                    #end
                                };
                            };
                            cur.angvel=cur.kinangvel;
                            if(cur.pre_posx!=ZPP_Const.POSINF){
                                var dx:Float;
                                var dy:Float;
                                {
                                    dx=cur.posx-cur.pre_posx;
                                    dy=cur.posy-cur.pre_posy;
                                };
                                {
                                    var t=(idt);
                                    {
                                        #if NAPE_ASSERT var res={
                                            !({
                                                #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                                ret;
                                                #else Math.isNaN(t);
                                                #end
                                            });
                                        };
                                        if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.vel"+",in b: "+"d"+",in s: "+"idt"+")");
                                        #end
                                    };
                                    cur.velx+=dx*t;
                                    cur.vely+=dy*t;
                                };
                                cur.angvel+=(cur.rot-cur.pre_rot)*idt;
                            }
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
        {
            {
                var cx_ite=kinematics.begin();
                while(cx_ite!=null){
                    var cur=cx_ite.elem();
                    {
                        if(cur.shapes.empty())throw "Error: Cannot simulate an empty Body";
                        cur.validate_mass();
                        cur.validate_inertia();
                        cur.validate_aabb();
                        cur.validate_gravMass();
                        cur.validate_worldCOM();
                        cur.validate_axis();
                        {
                            var cx_ite=cur.shapes.begin();
                            while(cx_ite!=null){
                                var s=cx_ite.elem();
                                {
                                    if(s.isPolygon()){
                                        var res=s.polygon.valid();
                                        if(res!=ValidationResult.VALID){
                                            throw "Error: Cannot simulate with an invalid Polygon : "+s.polygon.outer.toString()+" is invalid : "+res.toString();
                                        }
                                        s.polygon.validate_gaxi();
                                    }
                                };
                                cx_ite=cx_ite.next;
                            }
                        };
                        if(true){
                            {
                                cur.velx=cur.kinvelx;
                                cur.vely=cur.kinvely;
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.velx);
                                            ret;
                                            #else Math.isNaN(cur.velx);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(cur.velx)"+") :: "+("vec_set(in n: "+"cur.vel"+",in x: "+"cur.kinvelx"+",in y: "+"cur.kinvely"+")");
                                    #end
                                };
                                {
                                    #if NAPE_ASSERT var res={
                                        !({
                                            #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.vely);
                                            ret;
                                            #else Math.isNaN(cur.vely);
                                            #end
                                        });
                                    };
                                    if(!res)throw "assert("+"!assert_isNaN(cur.vely)"+") :: "+("vec_set(in n: "+"cur.vel"+",in x: "+"cur.kinvelx"+",in y: "+"cur.kinvely"+")");
                                    #end
                                };
                            };
                            cur.angvel=cur.kinangvel;
                            if(cur.pre_posx!=ZPP_Const.POSINF){
                                var dx:Float;
                                var dy:Float;
                                {
                                    dx=cur.posx-cur.pre_posx;
                                    dy=cur.posy-cur.pre_posy;
                                };
                                {
                                    var t=(idt);
                                    {
                                        #if NAPE_ASSERT var res={
                                            !({
                                                #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                                ret;
                                                #else Math.isNaN(t);
                                                #end
                                            });
                                        };
                                        if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.vel"+",in b: "+"d"+",in s: "+"idt"+")");
                                        #end
                                    };
                                    cur.velx+=dx*t;
                                    cur.vely+=dy*t;
                                };
                                cur.angvel+=(cur.rot-cur.pre_rot)*idt;
                            }
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function updateVel(dt:Float){
        var pre=null;
        {
            var cx_ite=live.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                {
                    {
                        var t=(cur.gravMass);
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                    ret;
                                    #else Math.isNaN(t);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.force"+",in b: "+"gravity"+",in s: "+"cur.gravMass"+")");
                            #end
                        };
                        cur.forcex+=gravityx*t;
                        cur.forcey+=gravityy*t;
                    };
                    {
                        var t=(-ZPP_Config.GLOBAL_LIN_DRAG*cur.mass);
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                    ret;
                                    #else Math.isNaN(t);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.force"+",in b: "+"cur.vel"+",in s: "+"-ZPP_Config.GLOBAL_LIN_DRAG*cur.mass"+")");
                            #end
                        };
                        cur.forcex+=cur.velx*t;
                        cur.forcey+=cur.vely*t;
                    };
                    if(cur.smass!=0.0){
                        var t=(dt*cur.imass);
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                    ret;
                                    #else Math.isNaN(t);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.vel"+",in b: "+"cur.force"+",in s: "+"dt*cur.imass"+")");
                            #end
                        };
                        cur.velx+=cur.forcex*t;
                        cur.vely+=cur.forcey*t;
                    };
                    {
                        cur.forcex=0;
                        cur.forcey=0;
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.forcex);
                                    ret;
                                    #else Math.isNaN(cur.forcex);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.forcex)"+") :: "+("vec_set(in n: "+"cur.force"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.forcey);
                                    ret;
                                    #else Math.isNaN(cur.forcey);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.forcey)"+") :: "+("vec_set(in n: "+"cur.force"+",in x: "+"0"+",in y: "+"0"+")");
                            #end
                        };
                    };
                    if(cur.sinertia!=0.0){
                        var dpx:Float;
                        var dpy:Float;
                        {
                            dpx=cur.worldCOMx-cur.posx;
                            dpy=cur.worldCOMy-cur.posy;
                        };
                        cur.torque+=(gravityy*dpx-gravityx*dpy)*cur.gravMass;
                        cur.torque-=cur.angvel*ZPP_Config.GLOBAL_ANG_DRAG*cur.inertia;
                        cur.angvel+=cur.torque*dt*cur.iinertia;
                    }
                    cur.torque=0;
                    pre=cx_ite;
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function updatePos(dt:Float){
        {
            var cx_ite=live.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                {
                    if(cur.smass!=0.0){
                        {
                            var t=(dt);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.pos"+",in b: "+"cur.vel"+",in s: "+"dt"+")");
                                #end
                            };
                            cur.posx+=cur.velx*t;
                            cur.posy+=cur.vely*t;
                        };
                        cur.invalidate_pos();
                    }
                    if(cur.sinertia!=0.0){
                        cur.rot+=cur.angvel*dt;
                        cur.invalidate_rot();
                    }
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function updatePosBias(){
        {
            var cx_ite=kinematics.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                {
                    {
                        cur.pre_posx=cur.posx;
                        cur.pre_posy=cur.posy;
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.pre_posx);
                                    ret;
                                    #else Math.isNaN(cur.pre_posx);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.pre_posx)"+") :: "+("vec_set(in n: "+"cur.pre_pos"+",in x: "+"cur.posx"+",in y: "+"cur.posy"+")");
                            #end
                        };
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.pre_posy);
                                    ret;
                                    #else Math.isNaN(cur.pre_posy);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.pre_posy)"+") :: "+("vec_set(in n: "+"cur.pre_pos"+",in x: "+"cur.posx"+",in y: "+"cur.posy"+")");
                            #end
                        };
                    };
                    cur.pre_rot=cur.rot;
                };
                cx_ite=cx_ite.next;
            }
        };
        {
            var cx_ite=live.begin();
            while(cx_ite!=null){
                var cur=cx_ite.elem();
                {
                    {
                        cur.pre_posx=cur.posx;
                        cur.pre_posy=cur.posy;
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.pre_posx);
                                    ret;
                                    #else Math.isNaN(cur.pre_posx);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.pre_posx)"+") :: "+("vec_set(in n: "+"cur.pre_pos"+",in x: "+"cur.posx"+",in y: "+"cur.posy"+")");
                            #end
                        };
                        {
                            #if NAPE_ASSERT var res={
                                !({
                                    #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.pre_posy);
                                    ret;
                                    #else Math.isNaN(cur.pre_posy);
                                    #end
                                });
                            };
                            if(!res)throw "assert("+"!assert_isNaN(cur.pre_posy)"+") :: "+("vec_set(in n: "+"cur.pre_pos"+",in x: "+"cur.posx"+",in y: "+"cur.posy"+")");
                            #end
                        };
                    };
                    if(cur.smass!=0.0){
                        {
                            var t=(1.0);
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                                        ret;
                                        #else Math.isNaN(t);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"cur.pos"+",in b: "+"cur.bias_vel"+",in s: "+"1.0"+")");
                                #end
                            };
                            cur.posx+=cur.bias_velx*t;
                            cur.posy+=cur.bias_vely*t;
                        };
                        {
                            cur.bias_velx=0;
                            cur.bias_vely=0;
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.bias_velx);
                                        ret;
                                        #else Math.isNaN(cur.bias_velx);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(cur.bias_velx)"+") :: "+("vec_set(in n: "+"cur.bias_vel"+",in x: "+"0"+",in y: "+"0"+")");
                                #end
                            };
                            {
                                #if NAPE_ASSERT var res={
                                    !({
                                        #if flash9 var ret:Bool=untyped __global__["isNaN"](cur.bias_vely);
                                        ret;
                                        #else Math.isNaN(cur.bias_vely);
                                        #end
                                    });
                                };
                                if(!res)throw "assert("+"!assert_isNaN(cur.bias_vely)"+") :: "+("vec_set(in n: "+"cur.bias_vel"+",in x: "+"0"+",in y: "+"0"+")");
                                #end
                            };
                        };
                        cur.invalidate_pos();
                    }
                    cur.pre_rot=cur.rot;
                    if(cur.sinertia!=0.0){
                        cur.rot+=cur.bias_angvel;
                        cur.bias_angvel=0.0;
                        cur.invalidate_rot();
                    }
                };
                cx_ite=cx_ite.next;
            }
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function prestep(dt:Float){
        {
            var cx_ite=constraints.begin();
            while(cx_ite!=null){
                var con=cx_ite.elem();
                {
                    con.preStep(dt);
                };
                cx_ite=cx_ite.next;
            }
        };
        {
            var pre=null;
            {
                var cx_ite=c_arbiters_true.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    {
                        if((arb.b1.sleeping&&arb.b2.sleeping)&&!arb.cleared){
                            arb.sleep_stamp=stamp;
                            arb.sleeping=true;
                            cx_ite=c_arbiters_true.erase(pre);
                            continue;
                        }
                        if(((arb.type==ZPP_Arbiter.SENSOR||arb.type==ZPP_Arbiter.FLUID)&&arb.up_stamp<stamp)||arb.up_stamp+ZPP_Config.PERSIST<stamp||arb.cleared){
                            if(!arb.cleared)map_arb.remove(arb.id);
                            arb.retire();
                            cx_ite=c_arbiters_true.erase(pre);
                            continue;
                        }
                        var pact=arb.active;
                        arb.active=arb.up_stamp==stamp;
                        if(pact!=arb.active){
                            arb.b1.arbiters.modified=true;
                            arb.b2.arbiters.modified=true;
                            c_arbiters_true.modified=true;
                        }
                        if(arb.active)arb.preStep();
                        pre=cx_ite;
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
        {
            var pre=null;
            {
                var cx_ite=c_arbiters_false.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    {
                        if((arb.b1.sleeping&&arb.b2.sleeping)&&!arb.cleared){
                            arb.sleep_stamp=stamp;
                            arb.sleeping=true;
                            cx_ite=c_arbiters_false.erase(pre);
                            continue;
                        }
                        if(((arb.type==ZPP_Arbiter.SENSOR||arb.type==ZPP_Arbiter.FLUID)&&arb.up_stamp<stamp)||arb.up_stamp+ZPP_Config.PERSIST<stamp||arb.cleared){
                            if(!arb.cleared)map_arb.remove(arb.id);
                            arb.retire();
                            cx_ite=c_arbiters_false.erase(pre);
                            continue;
                        }
                        var pact=arb.active;
                        arb.active=arb.up_stamp==stamp;
                        if(pact!=arb.active){
                            arb.b1.arbiters.modified=true;
                            arb.b2.arbiters.modified=true;
                            c_arbiters_false.modified=true;
                        }
                        if(arb.active)arb.preStep();
                        pre=cx_ite;
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
        {
            var pre=null;
            {
                var cx_ite=f_arbiters.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    {
                        if((arb.b1.sleeping&&arb.b2.sleeping)&&!arb.cleared){
                            arb.sleep_stamp=stamp;
                            arb.sleeping=true;
                            cx_ite=f_arbiters.erase(pre);
                            continue;
                        }
                        if(((arb.type==ZPP_Arbiter.SENSOR||arb.type==ZPP_Arbiter.FLUID)&&arb.up_stamp<stamp)||arb.up_stamp+ZPP_Config.PERSIST<stamp||arb.cleared){
                            if(!arb.cleared)map_arb.remove(arb.id);
                            arb.retire();
                            cx_ite=f_arbiters.erase(pre);
                            continue;
                        }
                        var pact=arb.active;
                        arb.active=arb.up_stamp==stamp;
                        if(pact!=arb.active){
                            arb.b1.arbiters.modified=true;
                            arb.b2.arbiters.modified=true;
                            f_arbiters.modified=true;
                        }
                        if(arb.active)arb.preStep(this,dt);
                        pre=cx_ite;
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
        {
            var pre=null;
            {
                var cx_ite=s_arbiters.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    {
                        if((arb.b1.sleeping&&arb.b2.sleeping)&&!arb.cleared){
                            arb.sleep_stamp=stamp;
                            arb.sleeping=true;
                            cx_ite=s_arbiters.erase(pre);
                            continue;
                        }
                        if(((arb.type==ZPP_Arbiter.SENSOR||arb.type==ZPP_Arbiter.FLUID)&&arb.up_stamp<stamp)||arb.up_stamp+ZPP_Config.PERSIST<stamp||arb.cleared){
                            if(!arb.cleared)map_arb.remove(arb.id);
                            arb.retire();
                            cx_ite=s_arbiters.erase(pre);
                            continue;
                        }
                        var pact=arb.active;
                        arb.active=arb.up_stamp==stamp;
                        if(pact!=arb.active){
                            arb.b1.arbiters.modified=true;
                            arb.b2.arbiters.modified=true;
                            s_arbiters.modified=true;
                        }
                        {};
                        pre=cx_ite;
                    };
                    cx_ite=cx_ite.next;
                }
            };
        };
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function iterate(times:Int,elastic:Bool){
        for(i in 0...times){
            {
                var cx_ite=constraints.begin();
                while(cx_ite!=null){
                    var con=cx_ite.elem();
                    {
                        con.applyImpulse();
                    };
                    cx_ite=cx_ite.next;
                }
            };
            {
                var cx_ite=f_arbiters.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    if(arb.active)arb.applyImpulse();
                    cx_ite=cx_ite.next;
                }
            };
            {
                var cx_ite=c_arbiters_false.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    if(arb.active)arb.applyImpulse(elastic);
                    cx_ite=cx_ite.next;
                }
            };
            {
                var cx_ite=c_arbiters_true.begin();
                while(cx_ite!=null){
                    var arb=cx_ite.elem();
                    if(arb.active)arb.applyImpulse(elastic);
                    cx_ite=cx_ite.next;
                }
            };
        }
    }
    #if(flash9&&flib)@:ns("flibdel")#end public inline function warmStart(){
        {
            var cx_ite=c_arbiters_false.begin();
            while(cx_ite!=null){
                var arb=cx_ite.elem();
                if(arb.active)arb.applyImpulseCache();
                cx_ite=cx_ite.next;
            }
        };
        {
            var cx_ite=c_arbiters_true.begin();
            while(cx_ite!=null){
                var arb=cx_ite.elem();
                if(arb.active)arb.applyImpulseCache();
                cx_ite=cx_ite.next;
            }
        };
    }
    
    public inline function narrowPhase_false(s1:ZPP_Shape,s2:ZPP_Shape){
        var b1=s1.body;
        var b2=s2.body;
        if((b1!=b2)){
            var gcol=s1.filter.shouldCollide(s2.filter)&&!(b1.imass==0&&b2.imass==0&&b1.iinertia==0&&b2.iinertia==0);
            var scol=s1.filter.shouldSense(s2.filter);
            var fcol=(s1.fluidEnabled||s2.fluidEnabled)&&s1.filter.shouldFlow(s2.filter)&&!((s1.fluidEnabled&&b1.isDynamic()&&!s2.fluidEnabled&&!b2.isDynamic())||(s2.fluidEnabled&&b2.isDynamic()&&!s1.fluidEnabled&&!b1.isDynamic())||(s1.fluidEnabled&&!b1.isDynamic()&&!b2.isDynamic())||(s2.fluidEnabled&&!b2.isDynamic()&&!b1.isDynamic()));
            if(scol||gcol||fcol){
                var sa,sb;
                if(s1.type>s2.type){
                    sa=s2;
                    sb=s1;
                }
                else if(s1.type==s2.type){
                    if(s1.id<s2.id){
                        sa=s1;
                        sb=s2;
                    }
                    else{
                        sb=s1;
                        sa=s2;
                    }
                }
                else{
                    sa=s1;
                    sb=s2;
                }
                var reverse=sa==s2;
                var id=({
                    #if NAPE_ASSERT var A=sa.id;
                    var B=sb.id;
                    {
                        #if NAPE_ASSERT var res={
                            A<=B;
                        };
                        if(!res)throw "assert("+"A<=B"+") :: "+("ordered_id(in a: "+"sa.id"+", in b: "+"sb.id"+")");
                        #end
                    };
                    (A<<16)|B;
                    #else((sa.id)<<16)|(sb.id);
                    #end
                });
                if(fcol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZPP_FluidArbiter.zpp_pool==null)new ZPP_FluidArbiter();
                        else{
                            var ret=ZPP_FluidArbiter.zpp_pool;
                            ZPP_FluidArbiter.zpp_pool=ret.next;
                            ret;
                        }
                    }
                    else{
                        if(xarb.fluidarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZPP_FluidArbiter.zpp_pool==null)new ZPP_FluidArbiter();
                                else{
                                    var ret=ZPP_FluidArbiter.zpp_pool;
                                    ZPP_FluidArbiter.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else arb=xarb.fluidarb;
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.flowCollide(sa,sb,arb)){
                            if(first){
                                arb.f_assign(s1,s2,id);
                                f_arbiters.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                f_arbiters.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_FluidArbiter"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_FluidArbiter.zpp_pool;
                            ZPP_FluidArbiter.zpp_pool=o;
                        };
                    }
                }
                else if(gcol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZDD.zpp_pool==null)new ZDD();
                        else{
                            var ret=ZDD.zpp_pool;
                            ZDD.zpp_pool=ret.next;
                            ret;
                        }
                    };
                    else{
                        if(xarb.colarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZDD.zpp_pool==null)new ZDD();
                                else{
                                    var ret=ZDD.zpp_pool;
                                    ZDD.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else if(xarb.colarb.kind!=ZPP_ColArbiter.DD){
                            var oarb:Dynamic=[xarb.colarb.aSD,xarb.colarb.aDD][xarb.colarb.kind];
                            arb={
                                if(ZDD.zpp_pool==null)new ZDD();
                                else{
                                    var ret=ZDD.zpp_pool;
                                    ZDD.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            {
                                var t=arb.contacts;
                                arb.contacts=oarb.contacts;
                                oarb.contacts=t;
                            };
                            {
                                var t=arb.innards;
                                arb.innards=oarb.innards;
                                oarb.innards=t;
                            };
                            {
                                var t=arb.wrap_contacts;
                                arb.wrap_contacts=oarb.wrap_contacts;
                                oarb.wrap_contacts=t;
                            };
                            {
                                var cx_ite=arb.contacts.begin();
                                while(cx_ite!=null){
                                    var con=cx_ite.elem();
                                    con.arbiter=arb;
                                    cx_ite=cx_ite.next;
                                }
                            };
                            arb.id=oarb.id;
                            arb.stamp=oarb.stamp;
                            arb.up_stamp=oarb.up_stamp;
                            if(oarb.b2.isStatic()){
                                arb.ws1=oarb.ws2;
                                arb.ws2=oarb.ws1;
                                arb.s1=oarb.s2;
                                arb.s2=oarb.s1;
                                arb.b1=oarb.b2;
                                arb.b2=oarb.b1;
                            }
                            else{
                                arb.ws1=oarb.ws1;
                                arb.ws2=oarb.ws2;
                                arb.s1=oarb.s1;
                                arb.s2=oarb.s2;
                                arb.b1=oarb.b1;
                                arb.b2=oarb.b2;
                            }
                            arb.cleared=oarb.cleared;
                            arb.active=oarb.active;
                            arb.sleeping=oarb.sleeping;
                            arb.sleep_stamp=oarb.sleep_stamp;
                            arb.restitution=oarb.restitution;
                            arb.stat_fric=oarb.stat_fric;
                            arb.dyn_fric=oarb.dyn_fric;
                            xarb.lazyRetire(this,null);
                            map_arb.set(arb.id,arb);
                            arb.b1.arbiters.add(arb);
                            arb.b2.arbiters.add(arb);
                            if(!oarb.sleeping)c_arbiters_false.add(arb);
                            reverse=sa!=arb.s1;
                        }
                        else{
                            arb=xarb.colarb.aDD;
                            if(false){
                                if(!arb.b1.isStatic())arb.swap_features();
                            }
                            reverse=sa!=arb.s1;
                        }
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.contactCollide_false(sa,sb,arb,reverse)){
                            if(first){
                                arb.assign(s1,s2,id);
                                c_arbiters_false.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                c_arbiters_false.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZDD"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZDD.zpp_pool;
                            ZDD.zpp_pool=o;
                        };
                    }
                }
                else if(scol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZPP_SensorArbiter.zpp_pool==null)new ZPP_SensorArbiter();
                        else{
                            var ret=ZPP_SensorArbiter.zpp_pool;
                            ZPP_SensorArbiter.zpp_pool=ret.next;
                            ret;
                        }
                    }
                    else{
                        if(xarb.sensorarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZPP_SensorArbiter.zpp_pool==null)new ZPP_SensorArbiter();
                                else{
                                    var ret=ZPP_SensorArbiter.zpp_pool;
                                    ZPP_SensorArbiter.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else arb=xarb.sensorarb;
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.testCollide(sa,sb)){
                            if(first){
                                arb.s_assign(s1,s2,id);
                                s_arbiters.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                s_arbiters.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_SensorArbiter"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_SensorArbiter.zpp_pool;
                            ZPP_SensorArbiter.zpp_pool=o;
                        };
                    }
                }
            }
        }
    }
    #if(flash9&&flib)@:keep var flibdel_narrowPhase(false):Void->Void;
    #end public inline function narrowPhase_true(s1:ZPP_Shape,s2:ZPP_Shape){
        var b1=s1.body;
        var b2=s2.body;
        if((true)){
            var gcol=s1.filter.shouldCollide(s2.filter)&&!(b1.imass==0&&b2.imass==0&&b1.iinertia==0&&b2.iinertia==0);
            var scol=s1.filter.shouldSense(s2.filter);
            var fcol=(s1.fluidEnabled||s2.fluidEnabled)&&s1.filter.shouldFlow(s2.filter)&&!((s1.fluidEnabled&&b1.isDynamic()&&!s2.fluidEnabled&&!b2.isDynamic())||(s2.fluidEnabled&&b2.isDynamic()&&!s1.fluidEnabled&&!b1.isDynamic())||(s1.fluidEnabled&&!b1.isDynamic()&&!b2.isDynamic())||(s2.fluidEnabled&&!b2.isDynamic()&&!b1.isDynamic()));
            if(scol||gcol||fcol){
                var sa,sb;
                if(s1.type>s2.type){
                    sa=s2;
                    sb=s1;
                }
                else if(s1.type==s2.type){
                    if(s1.id<s2.id){
                        sa=s1;
                        sb=s2;
                    }
                    else{
                        sb=s1;
                        sa=s2;
                    }
                }
                else{
                    sa=s1;
                    sb=s2;
                }
                var reverse=sa==s2;
                var id=({
                    #if NAPE_ASSERT var A=sa.id;
                    var B=sb.id;
                    {
                        #if NAPE_ASSERT var res={
                            A<=B;
                        };
                        if(!res)throw "assert("+"A<=B"+") :: "+("ordered_id(in a: "+"sa.id"+", in b: "+"sb.id"+")");
                        #end
                    };
                    (A<<16)|B;
                    #else((sa.id)<<16)|(sb.id);
                    #end
                });
                if(fcol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZPP_FluidArbiter.zpp_pool==null)new ZPP_FluidArbiter();
                        else{
                            var ret=ZPP_FluidArbiter.zpp_pool;
                            ZPP_FluidArbiter.zpp_pool=ret.next;
                            ret;
                        }
                    }
                    else{
                        if(xarb.fluidarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZPP_FluidArbiter.zpp_pool==null)new ZPP_FluidArbiter();
                                else{
                                    var ret=ZPP_FluidArbiter.zpp_pool;
                                    ZPP_FluidArbiter.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else arb=xarb.fluidarb;
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.flowCollide(sa,sb,arb)){
                            if(first){
                                arb.f_assign(s1,s2,id);
                                f_arbiters.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                f_arbiters.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_FluidArbiter"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_FluidArbiter.zpp_pool;
                            ZPP_FluidArbiter.zpp_pool=o;
                        };
                    }
                }
                else if(gcol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZSD.zpp_pool==null)new ZSD();
                        else{
                            var ret=ZSD.zpp_pool;
                            ZSD.zpp_pool=ret.next;
                            ret;
                        }
                    };
                    else{
                        if(xarb.colarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZSD.zpp_pool==null)new ZSD();
                                else{
                                    var ret=ZSD.zpp_pool;
                                    ZSD.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else if(xarb.colarb.kind!=ZPP_ColArbiter.SD){
                            var oarb:Dynamic=[xarb.colarb.aSD,xarb.colarb.aDD][xarb.colarb.kind];
                            arb={
                                if(ZSD.zpp_pool==null)new ZSD();
                                else{
                                    var ret=ZSD.zpp_pool;
                                    ZSD.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            {
                                var t=arb.contacts;
                                arb.contacts=oarb.contacts;
                                oarb.contacts=t;
                            };
                            {
                                var t=arb.innards;
                                arb.innards=oarb.innards;
                                oarb.innards=t;
                            };
                            {
                                var t=arb.wrap_contacts;
                                arb.wrap_contacts=oarb.wrap_contacts;
                                oarb.wrap_contacts=t;
                            };
                            {
                                var cx_ite=arb.contacts.begin();
                                while(cx_ite!=null){
                                    var con=cx_ite.elem();
                                    con.arbiter=arb;
                                    cx_ite=cx_ite.next;
                                }
                            };
                            arb.id=oarb.id;
                            arb.stamp=oarb.stamp;
                            arb.up_stamp=oarb.up_stamp;
                            if(oarb.b2.isStatic()){
                                arb.ws1=oarb.ws2;
                                arb.ws2=oarb.ws1;
                                arb.s1=oarb.s2;
                                arb.s2=oarb.s1;
                                arb.b1=oarb.b2;
                                arb.b2=oarb.b1;
                            }
                            else{
                                arb.ws1=oarb.ws1;
                                arb.ws2=oarb.ws2;
                                arb.s1=oarb.s1;
                                arb.s2=oarb.s2;
                                arb.b1=oarb.b1;
                                arb.b2=oarb.b2;
                            }
                            arb.cleared=oarb.cleared;
                            arb.active=oarb.active;
                            arb.sleeping=oarb.sleeping;
                            arb.sleep_stamp=oarb.sleep_stamp;
                            arb.restitution=oarb.restitution;
                            arb.stat_fric=oarb.stat_fric;
                            arb.dyn_fric=oarb.dyn_fric;
                            xarb.lazyRetire(this,null);
                            map_arb.set(arb.id,arb);
                            arb.b1.arbiters.add(arb);
                            arb.b2.arbiters.add(arb);
                            if(!oarb.sleeping)c_arbiters_true.add(arb);
                            reverse=sa!=arb.s1;
                        }
                        else{
                            arb=xarb.colarb.aSD;
                            if(true){
                                if(!arb.b1.isStatic())arb.swap_features();
                            }
                            reverse=sa!=arb.s1;
                        }
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.contactCollide_true(sa,sb,arb,reverse)){
                            if(first){
                                arb.assign(s1,s2,id);
                                c_arbiters_true.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                c_arbiters_true.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZSD"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZSD.zpp_pool;
                            ZSD.zpp_pool=o;
                        };
                    }
                }
                else if(scol){
                    var xarb=map_arb.get(id);
                    var first=xarb==null;
                    var arb;
                    if(first)arb={
                        if(ZPP_SensorArbiter.zpp_pool==null)new ZPP_SensorArbiter();
                        else{
                            var ret=ZPP_SensorArbiter.zpp_pool;
                            ZPP_SensorArbiter.zpp_pool=ret.next;
                            ret;
                        }
                    }
                    else{
                        if(xarb.sensorarb==null){
                            xarb.lazyRetire(this,null);
                            arb={
                                if(ZPP_SensorArbiter.zpp_pool==null)new ZPP_SensorArbiter();
                                else{
                                    var ret=ZPP_SensorArbiter.zpp_pool;
                                    ZPP_SensorArbiter.zpp_pool=ret.next;
                                    ret;
                                }
                            };
                            first=true;
                        }
                        else arb=xarb.sensorarb;
                    }
                    if(first||arb.stamp!=stamp){
                        arb.stamp=stamp;
                        if(ZPP_Collide.testCollide(sa,sb)){
                            if(first){
                                arb.s_assign(s1,s2,id);
                                s_arbiters.add(arb);
                                map_arb.set(id,arb);
                            }
                            arb.up_stamp=arb.stamp;
                            if(arb.b1.sleeping&&arb.b1.isDynamic())wake(arb.b1);
                            if(arb.b2.sleeping&&arb.b2.isDynamic())wake(arb.b2);
                            if(arb.sleeping){
                                arb.sleeping=false;
                                s_arbiters.add(arb);
                            }
                        }
                        else if(first){
                            var o=arb;
                            {
                                #if NAPE_ASSERT var res={
                                    o!=null;
                                };
                                if(!res)throw "assert("+"o!=null"+") :: "+("Free(in T: "+"ZPP_SensorArbiter"+", in obj: "+"arb"+")");
                                #end
                            };
                            o.free();
                            o.next=ZPP_SensorArbiter.zpp_pool;
                            ZPP_SensorArbiter.zpp_pool=o;
                        };
                    }
                }
            }
        }
    }
    #if(flash9&&flib)@:keep var flibdel_narrowPhase(true):Void->Void;
    #end
}
